/*
*	Copyright (c) 2009 Brent Mombourquette
*
*	Permission is hereby granted, free of charge, to any person
*	obtaining a copy of this software and associated documentation
*	files (the "Software"), to deal in the Software without
*	restriction, including without limitation the rights to use,
*	copy, modify, merge, publish, distribute, sublicense, and/or sell
*	copies of the Software, and to permit persons to whom the
*	Software is furnished to do so, subject to the following
*	conditions:
*
*	The above copyright notice and this permission notice shall be
*	included in all copies or substantial portions of the Software.
*
*	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
*	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
*	OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
*	NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
*	HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
*	WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
*	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
*	OTHER DEALINGS IN THE SOFTWARE.
*
*	This file contains functions that alter the look and structure of the graph from graph_page.html.
*/

var graphParticles = new Array();	// An array containing objects, where each object has its database row number and the corresponding particle

var manipulateGraph = {
	
	/*
	 * Delete node from the graph.
	 * Globals: nodes [ see build_graph.js ]
	 * @param {DataNode} node
	 * @param {Particle} mNode
	 * @param {ForceDirectedLayout} layout
	 */
	deleteNode: function(node, mNode, layout) {
		layout.view.removeNode(mNode); // Remove the HTML node element
		database.deleteNode(node); // Delete from the database
		graphHTMLControl.closeNodeContext();
		nodes[node.url] = null; // Remove this node from the dictionary of nodes
		manipulateGraph.removeNodeForces(node, mNode, layout); // Remove the forces
	},
	
	/*
	 * Delete edge from the database. The edge must also be deleted from the DOM structure, along with the Session Trail entry.
	 * The title of the destination node for this edge may have to be copied to the next instance of that destination in the database.
	 * @param {SVG Polyline Element} edge
	 * @param {SVG G Element} edgeDOMContainer
	 */
	deleteEdge: function(edge, edgeDOMContainer) {
		edgeDOMContainer.removeChild(edge); // Delete the edgeDOM object
		sessionTrail.removeEntry(edge.id); // Delete the corresponding entry in the Session Trail
		
		//First we need the information about this edge
		var edgeProperties = database.getEdgeProperties(edge);
		// Check to see if this edge will result in a node being a root node, after deletion
		var row = database.getNextRow(edgeProperties);
		
		if ( row ) { 	
			// Another row entry exists with this as the destination so it will not end up being a root node.
			// If the row at index edge.idx  is the first entry for destionation (the variable here) then this entry
			// has a potential user altered title. row is the NEXT edge for destination, following the edge being
			// deleted, so we chance row's title to what this edge's destination node's title is.
			// This has to be done since for each URL its user altered title is stored in the earliest
			// row where destination = that URL.
			if ( row > edge.idx) {
				database.updateTitle(row, edgeProperties.title);
			}
			database.deleteRow(edge.idx);
		} else {	// No other row entry exists so this destination will end up being a root node
			database.nullifySource(edge.idx);	
		}
		graphHTMLControl.closeEdgeContext();
		
		if (edge.direction) { //direction == 1 so particleB is the destination node, which will need to be fixed
			manipulateGraph.removeEdgeForces(edge.pA, edge.pB, edge.pB);
		} else { //direction == 0 so particleA is the destination node, which will need to be fixed
			manipulateGraph.removeEdgeForces(edge.pA, edge.pB, edge.pA);
		}
	},
	
	/*
	 * Remove the Magnets and Springs that involved node and its DOM particle
	 * @param {DataNode} node  
	 * @param {Particle} particle
	 * @param {ForceDirectedLayout} layout
	 */
	removeNodeForces: function(node, particle, layout) {
		var i, l;
		
		var magnets = layout.model.magnets;
		for ( i=0, l=magnets.length; i<l; i++ ) {
			if (magnets[i]) {
				// Check if this magnet involved particle
				if (magnets[i].a == particle || magnets[i].b == particle)
					magnets.splice(i, 1);
			}
		}
		var activeMagnets = layout.model.activeMagnets;
		for ( i=0, l=activeMagnets.length; i<l; i++ ) {
			if (activeMagnets[i]) {
				// Check if this active magnet involves particle
				if (activeMagnets[i].a == particle || activeMagnets[i].b == particle)
					activeMagnets.splice(i, 1);
			}
		}
		var springs = layout.model.springs;
		for ( i=0, l=springs.length; i<l; i++ ) {
			if (springs[i]) {
				// Check if this spring connects to particle
				if (springs[i].a == particle || springs[i].b == particle)
					springs.splice(i, 1);
			}
		}
		var activeSprings = layout.model.activeSprings;
		for ( i=0, l=activeSprings.length; i<l; i++ ) {
			if (activeSprings[i]) {
				// Check if this active spring connects to particle
				if (activeSprings[i].a == particle || activeSprings[i].b == particle)
					activeSprings.splice(i, 1);
			}
		}
	},
	
	/*
	 * Remove the Magnets and Spring between Particle a and Particle b
	 * Globals: layout
	 * @param {Particle} a
	 * @param {Particle} b
	 * @param {Particle} particleToFix			The particle that has to be set to fixed = true
	 */
	removeEdgeForces: function(a, b, particleToFix) {
		var i, l;
		
		var magnets = layout.model.magnets;
		for ( i=0, l=magnets.length; i<l; i++ ) {
			if (magnets[i]) {
				// Check if this magnet connects both particle a and partible b, and if so remove it.
				if ((magnets[i].a == a && magnets[i].b == b) || (magnets[i].a == b && magnets[i].b == a))
					magnets.splice(i, 1);
			}
		}
		var activeMagnets = layout.model.activeMagnets;
		for ( i=0, l=activeMagnets.length; i<l; i++ ) {
			if (activeMagnets[i]) {
				// Check if this active magnet connects both particle a and partible b, and if so remove it.
				if ((activeMagnets[i].a == a && activeMagnets[i].b == b) || (activeMagnets[i].a == b && activeMagnets[i].b == a))
					activeMagnets.splice(i, 1);
			}
		}
		var springs = layout.model.springs;
		for ( i=0, l=springs.length; i<l; i++ ) {
			if (springs[i]) {
				// Check if this spring connects both particle a and partible b, and if so remove it.
				if ((springs[i].a == a && springs[i].b == b) || (springs[i].a == b && springs[i].b == a))
					springs.splice(i, 1);
			}
		}
		var activeSprings = layout.model.activeSprings;
		for ( i=0, l=activeSprings.length; i<l; i++ ) {
			if (activeSprings[i]) {
				// Check if this active spring connects both particle a and partible b, and if so remove it.
				if ((activeSprings[i].a == a && activeSprings[i].b == b) || (activeSprings[i].a == b && activeSprings[i].b == a))
					activeSprings.splice(i, 1);
			}
		}
		
		particleToFix.fixed = true;
	},
	
	/*
	 * Extract the objects in graphParticles
	 * Globals: graphParticles
	 */
	saveCords: function() {
		for (var i=0; i < graphParticles.length; i++) {
			var obj = graphParticles[i];
			database.updateCords(obj['idx'], obj['particle'].positionX, obj['particle'].positionY);
		}
	}
}